package com.huo.util;

import com.huo.common.enumtype.R;
import com.huo.filestransport.vo.FtpFileInfo;
import com.huo.filestransport.vo.FtpServerInfo;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class FtpUtil {

	private final Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
	private FtpServerInfo ftpServerInfo;

	/**
	 * 获取ftp连接
	 * 
	 * @return
	 */
	public FTPClient getFTPConnection() {
		FTPClient ftp = null;
		logger.info("连接FTP ip：prot " + ftpServerInfo.getIp() + "：" + ftpServerInfo.getPort());
		try {
			ftp = new FTPClient();
			ftp.connect(ftpServerInfo.getIp(), ftpServerInfo.getPort());
			ftp.login(ftpServerInfo.getUsername(), ftpServerInfo.getPassword());
			ftp.enterLocalPassiveMode(); //打开专用的端口
			ftp.setBufferSize(1024*1024*10);//默认缓冲区大小是1024，也就是1K
			ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
			FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
			ftp.configure(conf);
		} catch (Exception e) {
			logger.error(e.getMessage(),e);	
		}
		int reply = ftp.getReplyCode();
		logger.info("连接返回结果：" + reply + " " + ftp);
		return ftp;
	}
	
	/**
	 * 获取ftp连接
	 * 
	 * @return
	 */
	public FTPClient getUpFTPConnection() {
		FTPClient ftp = null;
		logger.info("连接FTP upIp：upProt " + ftpServerInfo.getUpIp() + "：" + ftpServerInfo.getUpPort());
		try {
			ftp = new FTPClient();
			ftp.connect(ftpServerInfo.getUpIp(), ftpServerInfo.getUpPort());
			ftp.login(ftpServerInfo.getUpUsername(), ftpServerInfo.getUpPassword());
			//ftp.enterLocalPassiveMode(); //打开专用的端口
			ftp.setBufferSize(1024*1024*10);//默认缓冲区大小是1024，也就是1K
			ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
			FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
			ftp.configure(conf);
		} catch (Exception e) {
			logger.error(e.getMessage(),e);	
		}
		int reply = ftp.getReplyCode();
		logger.info("连接返回结果：" + reply + " " + ftp);
		return ftp;
	}
	
	
	
	
	
	/**
	 * 递归获取指定的文件目录
	 * @param
	 * @param fileDirectoryList
	 * @return
	 */
	public R readFTPFileDirectory(String ftpDirectory, List<String> fileDirectoryList, FTPClient ftp, List<FtpFileInfo> ftpFileList) {
		logger.info("递归文件目录：" + ftpDirectory);

		try {
			if(!ftp.changeWorkingDirectory(ftpDirectory)) {
				logger.info("文件目录：" + ftpDirectory + "不存在");
				return R.error("文件目录：" + ftpDirectory + "不存在");
			}
			FTPFile[] files = ftp.listFiles();
			for (FTPFile file : files) {
                if (file.isFile()) {
                	fileDirectoryList.add(ftpDirectory+file.getName());
                	FtpFileInfo ftpFileInfo = new FtpFileInfo();
                	ftpFileInfo.setFtpPath(ftpDirectory+file.getName());
                	ftpFileInfo.setFtpFile(file);
                	ftpFileList.add(ftpFileInfo);
                } else if (file.isDirectory()) {
                    // 需要加此判断。否则，ftp默认将项目文件所在目录之下的目录（./）与项目文件所在目录向上一级目录下的目录（../）都纳入递归，
                	//这样下去就陷入一个死循环了。需将其过滤掉。
                    if (!".".equals(file.getName()) && !"..".equals(file.getName())) {
                    	readFTPFileDirectory(ftpDirectory + file.getName() + "/",fileDirectoryList,ftp,ftpFileList);
                    }
                }
            }
		} catch (Exception e) {
			logger.error(e.getMessage(),e);	
			R.error("读取文件异常");
		}
		logger.info("递归读取到文件："+ftpDirectory + " " + fileDirectoryList.size() + fileDirectoryList.toString());
		return R.ok();
	}
	/**
	 * 递归获取本地文件
	 * @param localDirectory
	 * @param localFileList
	 * @return
	 */
	public R readLocalFileByDirectory(String localDirectory, List<String> localFileList,List<File> localFileInfoList) {
		logger.info("递归本地文件目录：" + localDirectory);
		File file = new File(localDirectory);
		try {
			if (file.exists()) {
				File[] files = file.listFiles();
				 if (null != files) {
		                for (File f : files) {
		                    if (f.isDirectory() && !f.getName().equals(".") && !f.getName().equals("..")) {
		                    	readLocalFileByDirectory(f.getPath(),localFileList,localFileInfoList);
		                    } else if (f.isFile()) {
		                    	localFileList.add(f.getPath());
		                    	localFileInfoList.add(f);
		                    }
		                }
		            }
			} else {
				logger.info("目录" + localDirectory + "不存在");
				return R.error("目录" + localDirectory + "不存在");
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
		logger.info("递归读取到文件->"+localDirectory + " " + localFileList.size() +" "+ localFileList.toString());
		return R.ok();
	}
	
	
	/**
	 * 下载指定的文件
	 * @param
	 * @param ftpPath
	 * @param localPath
	 */
	public R downloadFtpFileByFtpPath(String ftpPath, String localPath,FTPClient ftp) throws Exception {
		logger.info("开始下载文件：" + ftpPath);
		FTPFile[] files = ftp.listFiles(ftpPath);
		logger.info("文件个数：{}",files.length);
		if (files.length != 1) {
			logger.info("请求的ftp文件不存在"+ ftpPath);
			return R.error("请求的ftp文件不存在" + ftpPath);
		}
		long filesize = files[0].getSize();
		long createTime = files[0].getTimestamp().getTimeInMillis();
		String localFileDir = localPath + ftpPath.substring(0, ftpPath.lastIndexOf("/")) + "/";
		logger.info("localFileDir:{}",localFileDir);
		String localFile = localPath + ftpPath;
		File localDir = new File(localFileDir);
		if (!localDir.exists()) {
			localDir.mkdirs();
		}
		OutputStream outputStream = null;
		BufferedOutputStream bufferedoutputStream = null;
		try {
			outputStream = new FileOutputStream(localFile); 
			bufferedoutputStream = new BufferedOutputStream(outputStream); 
			ftp.retrieveFile(ftpPath, outputStream);
			logger.info("文件下载到" + localFile);
		} catch (Exception e) {
			logger.error(e.getMessage(),e);			
			return R.error("下载文件时失败：" + ftpPath);
		}finally {
			outputStream.close();
			bufferedoutputStream.close();
		}
		Map<String,Object> map = new HashMap<String,Object>();
		map.put("filesize",filesize);
		map.put("createTime",createTime);
		map.put("localFile",localFile);
		return R.ok(map);
	}
	
	public R getFtpFileInfo(String ftpPath,FTPClient ftp)throws Exception {
		logger.info("开始获取文件信息：" + ftpPath);
		if(ftpPath != null) {
			FTPFile[] files = ftp.listFiles(ftpPath);
			if(files.length == 1) {
				return R.ok(files[0]);
			}
		}else {
			return R.error();
		}
		return R.error();
		
	}
	
	/**
	 * 上传指定的文件
	 * @param ftpDirectory
	 * @param localPath
	 * @param ftp
	 * @return
	 */
	public R uploadFile(String ftpDirectory,String localPath,FTPClient ftp) {
		logger.info("上传文件开始：localPath->" + localPath +" ftpDirectory->"+ftpDirectory );
		FileInputStream input = null;
		try {
			if(ftp.changeWorkingDirectory(ftpDirectory)) {
				logger.info("文件目录：" + ftpDirectory + "已存在");
			}else {
				logger.info("文件目录：" + ftpDirectory + "不存在,进行创建");
				ftp.makeDirectory(ftpDirectory);
				ftp.changeWorkingDirectory(ftpDirectory);
			}
			File file = new File(localPath);
			input =new FileInputStream(file);
			boolean ftpUploadFlag = ftp.storeFile(getFileNamebyFtpPath(localPath), input);
			if(ftpUploadFlag) {
				logger.info("文件上传成功：" + localPath);
				return R.ok();
			}else {
				logger.info("文件上传失败：" + localPath);
				return R.error();
			}
		} catch (Exception e) {
			logger.error("文件上传失败：" + localPath + e.getMessage(),e);
		}finally {
			try {
				input.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		logger.info("上传文件结束：localPath->" + localPath +" ftpDirectory->"+ftpDirectory );
		return R.ok();
		
	}
	
	/**
	 * 关闭连接
	 * @param ftp
	 */
	public void closeFTPConnection(FTPClient ftp) {
		logger.info("关闭FTP连接");
		if (ftp != null && ftp.isConnected()) {
			try {
				ftp.logout();
				logger.info("ftp.logout();");
				ftp.disconnect();
				logger.info("ftp.disconnect()");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		logger.info("成功关闭FTP连接");
	}
	
	public String getFileNamebyFtpPath(String ftpPath) {
		if(ftpPath != null) {
			ftpPath = ftpPath.replace("\\", "/");
		}
		return  ftpPath.substring(ftpPath.lastIndexOf("/")+1,ftpPath.length());
	}
	
	/**
	 * 反斜线转为斜线
	 * @param backslash
	 * @return
	 */
	public String backslashToforwardslash(String backslash) {
		if(backslash != null && backslash.indexOf("\\") != -1) {
			backslash = backslash.replace("\\", "/");
		}
		return backslash;
	}
}
